package com.code.generator.provider;

import com.code.config.DataSourceInfo;
import com.code.config.source.DatasourceFactory;
import com.code.generator.GenerateParams;
import com.code.entity.metadata.Column;
import com.code.entity.metadata.Table;
import com.code.utils.DataProcessUtils;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SimpleMetadataProvider implements MetadataProvider {

    private static final Pattern PATTERN_CAMEL_IDENTIFY = Pattern.compile("[_|\\-]([a-z])");

    @Override
    public List<Table> getTables() {
        Connection connection = null;
        ResultSet tableResultSet;
        PreparedStatement tableStatement;
        List<Table> tables = new ArrayList<>();
        try {
            DataSource dataSource = DatasourceFactory.getDataSource();
            connection = dataSource.getConnection();
            String sql = String.format(DataSourceInfo.getTableSql(), DataSourceInfo.TABLE_SCHEMA.getValue());
            tableStatement = connection.prepareStatement(sql);
            tableResultSet = tableStatement.executeQuery();

            while (tableResultSet.next()) {
                Table table = new Table();
                table.setName(tableResultSet.getString("table_name"));
                table.setSchema(tableResultSet.getString("table_schema"));
                table.setComment(tableResultSet.getString("table_comment"));
                table.setDBase(DataSourceInfo.TABLE_SCHEMA.getValue());
                List<Column> columns = new ArrayList<>();
                table.setColumns(columns);
                sql = String.format(DataSourceInfo.getColumnSqlSql(), table.getSchema(), table.getName());
                PreparedStatement columnStatement = connection.prepareStatement(sql);
                ResultSet columnResultSet = columnStatement.executeQuery();
                while (columnResultSet.next()) {
                    Column column = new Column();
                    column.setSchema(columnResultSet.getString("table_schema"));
                    column.setTableName(columnResultSet.getString("table_name"));
                    String name = columnResultSet.getString("column_name");
                    column.setName(name);
                    column.setUpperCaseName(name.toUpperCase());
                    Matcher matcher = PATTERN_CAMEL_IDENTIFY.matcher(name.toLowerCase());
                    StringBuffer buffer = new StringBuffer();
                    while (matcher.find()) {
                        matcher.appendReplacement(buffer, matcher.group(1).toUpperCase());
                    }
                    matcher.appendTail(buffer);
                    String fieldKey = buffer.toString();
                    column.setProperty(fieldKey);
                    column.setPropertyGet(Character.toUpperCase(fieldKey.charAt(0)) + fieldKey.substring(1));
                    column.setComment(columnResultSet.getString("column_comment"));
                    String dataType = columnResultSet.getString("data_type");
                    if ("DECIMAL".equalsIgnoreCase(dataType) || "NUMERIC".equalsIgnoreCase(dataType)) {
                        table.setDecimal(true);
                    } else if ("DATE".equalsIgnoreCase(dataType)
                            || "DATETIME".equalsIgnoreCase(dataType)
                            || "TIMESTAMP".equalsIgnoreCase(dataType)) {
                        table.setDate(true);
                    }
                    column.setJdbcType(DataProcessUtils.getJdbcType(dataType));
                    column.setJavaType(DataProcessUtils.getJavaType(dataType));
                    column.setColumnType(columnResultSet.getString("column_type"));
                    column.setNullable("yes".equalsIgnoreCase(columnResultSet.getString("is_nullable")));
                    column.setMaxLength(columnResultSet.getLong("character_maximum_length"));
                    GenerateParams.setColumnInfo(columnResultSet, column);
                    columns.add(column);
                }
                tables.add(table);
                columnResultSet.close();
                columnStatement.close();
            }
            tableResultSet.close();
            tableStatement.close();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return tables;
    }

}
